import { KeyCode, KeyCodeUppercase } from "./types";

export * from "./types";

/**
 * 字符串不区分大小写，直接索引对应 KeyCode
 * @param str 字符串
 * @returns KeyCode
 */
export function stringAsKeyCode(str: string): KeyCode {
    return KeyCodeUppercase[str.toUpperCase()] ?? KeyCode.Unidentified;
}

/**
 * KeyCode 转字符串
 * @param keyCode KeyCode
 * @returns 字符串
 */
export function keyCodeAsString(keyCode: KeyCode): string {
    return KeyCode[keyCode];
}

/**
 * 根据快捷键字符串生成 KeyCode
 * @param str 快捷键字符串
 * @returns KeyCode
 */
export function convertShortcutStringToKeyCode(str: string): KeyCode {
    switch (str.toUpperCase()) {
        case "`":
        case "BACKQUOTE":
            return KeyCode.Backquote;
        case "BACKSLASH":
            return KeyCode.Backslash;
        case "[":
        case "BRACKETLEFT":
            return KeyCode.BracketLeft;
        case "]":
        case "BRACKETRIGHT":
            return KeyCode.BracketRight;
        case ",":
        case "COMMA":
            return KeyCode.Comma;
        case "0":
            return KeyCode.Digit0;
        case "1":
            return KeyCode.Digit1;
        case "2":
            return KeyCode.Digit2;
        case "3":
            return KeyCode.Digit3;
        case "4":
            return KeyCode.Digit4;
        case "5":
            return KeyCode.Digit5;
        case "6":
            return KeyCode.Digit6;
        case "7":
            return KeyCode.Digit7;
        case "8":
            return KeyCode.Digit8;
        case "9":
            return KeyCode.Digit9;
        case "NUM0":
        case "NUMPAD0":
            return KeyCode.Numpad0;
        case "NUM1":
        case "NUMPAD1":
            return KeyCode.Numpad1;
        case "NUM2":
        case "NUMPAD2":
            return KeyCode.Numpad2;
        case "NUM3":
        case "NUMPAD3":
            return KeyCode.Numpad3;
        case "NUM4":
        case "NUMPAD4":
            return KeyCode.Numpad4;
        case "NUM5":
        case "NUMPAD5":
            return KeyCode.Numpad5;
        case "NUM6":
        case "NUMPAD6":
            return KeyCode.Numpad6;
        case "NUM7":
        case "NUMPAD7":
            return KeyCode.Numpad7;
        case "NUM8":
        case "NUMPAD8":
            return KeyCode.Numpad8;
        case "NUM9":
        case "NUMPAD9":
            return KeyCode.Numpad9;
        case "=":
            return KeyCode.Equal;
        case "-":
            return KeyCode.Minus;
        case "Plus":
            return KeyCode.Plus;
        case ".":
        case "PERIOD":
            return KeyCode.Period;
        case "'":
        case "QUOTE":
            return KeyCode.Quote;

        case "\\":
        case "INTLBACKSLASH":
            return KeyCode.IntlBackslash;
        case "INTLRO":
            return KeyCode.IntlRo;
        case "INTLYEN":
            return KeyCode.IntlYen;

        case "ALTLEFT":
            return KeyCode.AltLeft;
        case "ALTRIGHT":
            return KeyCode.AltRight;
        case "SHIFTLEFT":
            return KeyCode.ShiftLeft;
        case "SHIFTRIGHT":
            return KeyCode.ShiftRight;
        case "CONTROLLEFT":
            return KeyCode.ControlLeft;
        case "CONTROLRIGHT":
            return KeyCode.ControlRight;
        case "SUPERLEFT":
            return KeyCode.SuperLeft;
        case "SUPERRIGHT":
            return KeyCode.SuperRight;

        case "SELECT":
            return KeyCode.Select;

        case "A":
            return KeyCode.KeyA;
        case "B":
            return KeyCode.KeyB;
        case "C":
            return KeyCode.KeyC;
        case "D":
            return KeyCode.KeyD;
        case "E":
            return KeyCode.KeyE;
        case "F":
            return KeyCode.KeyF;
        case "G":
            return KeyCode.KeyG;
        case "H":
            return KeyCode.KeyH;
        case "I":
            return KeyCode.KeyI;
        case "J":
            return KeyCode.KeyJ;
        case "K":
            return KeyCode.KeyK;
        case "L":
            return KeyCode.KeyL;
        case "M":
            return KeyCode.KeyM;
        case "N":
            return KeyCode.KeyN;
        case "O":
            return KeyCode.KeyO;
        case "P":
            return KeyCode.KeyP;
        case "Q":
            return KeyCode.KeyQ;
        case "R":
            return KeyCode.KeyR;
        case "S":
            return KeyCode.KeyS;
        case "T":
            return KeyCode.KeyT;
        case "U":
            return KeyCode.KeyU;
        case "V":
            return KeyCode.KeyV;
        case "W":
            return KeyCode.KeyW;
        case "X":
            return KeyCode.KeyX;
        case "Y":
            return KeyCode.KeyY;
        case "Z":
            return KeyCode.KeyZ;

        case ";":
        case "SEMICOLON":
            return KeyCode.Semicolon;
        case "/":
        case "SLASH":
            return KeyCode.Slash;
        case "BACKSPACE":
            return KeyCode.Backspace;
        case "CAPSLOCK":
            return KeyCode.CapsLock;
        case "CONTEXTMENU":
            return KeyCode.ContextMenu;
        case "ENTER":
            return KeyCode.Enter;
        case "SPACE":
            return KeyCode.Space;
        case "TAB":
            return KeyCode.Tab;
        case "CONVERT":
            return KeyCode.Convert;

        case "DELETE":
            return KeyCode.Delete;
        case "END":
            return KeyCode.End;
        case "HELP":
            return KeyCode.Help;
        case "HOME":
            return KeyCode.Home;
        case "INSERT":
            return KeyCode.Insert;
        case "PAGEDOWN":
            return KeyCode.PageDown;
        case "PAGEUP":
            return KeyCode.PageUp;

        case "DOWN":
        case "ARROWDOWN":
            return KeyCode.ArrowDown;
        case "UP":
        case "ARROWUP":
            return KeyCode.ArrowUp;
        case "LEFT":
        case "ARROWLEFT":
            return KeyCode.ArrowLeft;
        case "RIGHT":
        case "ARROWRIGHT":
            return KeyCode.ArrowRight;

        case "NUMLOCK":
            return KeyCode.NumLock;
        case "NUMADD":
        case "NUMPADADD":
            return KeyCode.NumpadAdd;
        case "NUMBACKSPACE":
        case "NUMPADBACKSPACE":
            return KeyCode.NumpadBackspace;
        case "NUMCLEAR":
        case "NUMPADCLEAR":
            return KeyCode.NumpadClear;
        case "NUMCLEARENTRY":
        case "NUMPADCLEARENTRY":
            return KeyCode.NumpadClearEntry;
        case "NUMCOMMA":
        case "NUMPADCOMMA":
            return KeyCode.NumpadComma;
        case "NUMDECIMAL":
        case "NUMPADDECIMAL":
            return KeyCode.NumpadDecimal;
        case "NUMDIVIDE":
        case "NUMPADDIVIDE":
            return KeyCode.NumpadDivide;
        case "NUMSUBTRACT":
        case "NUMPADSUBTRACT":
            return KeyCode.NumpadSubtract;
        case "NUMENTER":
        case "NUMPADENTER":
            return KeyCode.NumpadEnter;
        case "NUMEQUAL":
        case "NUMPADEQUAL":
            return KeyCode.NumpadEqual;
        case "NUMMULTIPLY":
        case "NUMPADMULTIPLY":
            return KeyCode.NumpadMultiply;
        case "NUMSTAR":
        case "NUMPADSTAR":
            return KeyCode.NumpadStar;

        case "ESC":
        case "ESCAPE":
            return KeyCode.Escape;
        case "FN":
            return KeyCode.Fn;
        case "FNLOCK":
            return KeyCode.FnLock;
        case "PRINTSCREEN":
            return KeyCode.PrintScreen;
        case "SCROLLLOCK":
            return KeyCode.ScrollLock;

        case "PAUSE":
            return KeyCode.Pause;

        case "VOLUMEMUTE":
            return KeyCode.AudioVolumeMute;
        case "VOLUMEDOWN":
            return KeyCode.AudioVolumeDown;
        case "VOLUMEUP":
            return KeyCode.AudioVolumeUp;
        case "MEDIANEXTTRACK":
            return KeyCode.MediaTrackNext;
        case "MEDIAPREVIOUSTRACK":
            return KeyCode.MediaTrackPrevious;
        case "MEDIAPLAYPAUSE":
            return KeyCode.MediaPlayPause;
        case "LAUNCHMAIL":
            return KeyCode.LaunchMail;
        case "LAUNCHAPP1":
            return KeyCode.LaunchApp1;
        case "LAUNCHAPP2":
            return KeyCode.LaunchApp2;

        case "SUSPEND":
            return KeyCode.Suspend;
        case "F1":
            return KeyCode.F1;
        case "F2":
            return KeyCode.F2;
        case "F3":
            return KeyCode.F3;
        case "F4":
            return KeyCode.F4;
        case "F5":
            return KeyCode.F5;
        case "F6":
            return KeyCode.F6;
        case "F7":
            return KeyCode.F7;
        case "F8":
            return KeyCode.F8;
        case "F9":
            return KeyCode.F9;
        case "F10":
            return KeyCode.F10;
        case "F11":
            return KeyCode.F11;
        case "F12":
            return KeyCode.F12;
        case "F13":
            return KeyCode.F13;
        case "F14":
            return KeyCode.F14;
        case "F15":
            return KeyCode.F15;
        case "F16":
            return KeyCode.F16;
        case "F17":
            return KeyCode.F17;
        case "F18":
            return KeyCode.F18;
        case "F19":
            return KeyCode.F19;
        case "F20":
            return KeyCode.F20;
        case "F21":
            return KeyCode.F21;
        case "F22":
            return KeyCode.F22;
        case "F23":
            return KeyCode.F23;
        case "F24":
            return KeyCode.F24;
        case "F25":
            return KeyCode.F25;
        case "F26":
            return KeyCode.F26;
        case "F27":
            return KeyCode.F27;
        case "F28":
            return KeyCode.F28;
        case "F29":
            return KeyCode.F29;
        case "F30":
            return KeyCode.F30;
        case "F31":
            return KeyCode.F31;
        case "F32":
            return KeyCode.F32;
        case "F33":
            return KeyCode.F33;
        case "F34":
            return KeyCode.F34;
        case "F35":
            return KeyCode.F35;
        default:
            return KeyCode.Unidentified;
    }
}

/**
 * 把 KeyCode 转成对应的快捷键字符串
 * @param keyCode KeyCode
 * @returns 快捷键字符串
 */
export function convertKeyCodeToShortcutString(keyCode: string | KeyCode): string {
    // 对于字符串，先转成 KeyCode
    if (typeof keyCode === "string") {
        keyCode = stringAsKeyCode(keyCode);
    }

    switch (keyCode) {
        case KeyCode.Backquote:
            return "`";
        case KeyCode.Backslash:
            return "Backslash";
        case KeyCode.BracketLeft:
            return "[";
        case KeyCode.BracketRight:
            return "]";
        case KeyCode.Comma:
            return ",";
        case KeyCode.Digit0:
            return "0";
        case KeyCode.Digit1:
            return "1";
        case KeyCode.Digit2:
            return "2";
        case KeyCode.Digit3:
            return "3";
        case KeyCode.Digit4:
            return "4";
        case KeyCode.Digit5:
            return "5";
        case KeyCode.Digit6:
            return "6";
        case KeyCode.Digit7:
            return "7";
        case KeyCode.Digit8:
            return "8";
        case KeyCode.Digit9:
            return "9";
        case KeyCode.Numpad0:
            return "Num0";
        case KeyCode.Numpad1:
            return "Num1";
        case KeyCode.Numpad2:
            return "Num2";
        case KeyCode.Numpad3:
            return "Num3";
        case KeyCode.Numpad4:
            return "Num4";
        case KeyCode.Numpad5:
            return "Num5";
        case KeyCode.Numpad6:
            return "Num6";
        case KeyCode.Numpad7:
            return "Num7";
        case KeyCode.Numpad8:
            return "Num8";
        case KeyCode.Numpad9:
            return "Num9";
        case KeyCode.Equal:
            return "=";
        case KeyCode.Minus:
            return "-";
        case KeyCode.Plus:
            return "Plus";
        case KeyCode.Period:
            return ".";
        case KeyCode.Quote:
            return "'";

        case KeyCode.IntlBackslash:
            return "\\";
        case KeyCode.IntlRo:
            return "IntlRo";
        case KeyCode.IntlYen:
            return "IntlYen";

        case KeyCode.AltLeft:
            return "AltLeft";
        case KeyCode.AltRight:
            return "AltRight";
        case KeyCode.ShiftLeft:
            return "ShiftLeft";
        case KeyCode.ShiftRight:
            return "ShiftRight";
        case KeyCode.ControlLeft:
            return "ControlLeft";
        case KeyCode.ControlRight:
            return "ControlRight";
        case KeyCode.SuperLeft:
            return "SuperLeft";
        case KeyCode.SuperRight:
            return "SuperRight";

        case KeyCode.Select:
            return "Select";

        case KeyCode.KeyA:
            return "A";
        case KeyCode.KeyB:
            return "B";
        case KeyCode.KeyC:
            return "C";
        case KeyCode.KeyD:
            return "D";
        case KeyCode.KeyE:
            return "E";
        case KeyCode.KeyF:
            return "F";
        case KeyCode.KeyG:
            return "G";
        case KeyCode.KeyH:
            return "H";
        case KeyCode.KeyI:
            return "I";
        case KeyCode.KeyJ:
            return "J";
        case KeyCode.KeyK:
            return "K";
        case KeyCode.KeyL:
            return "L";
        case KeyCode.KeyM:
            return "M";
        case KeyCode.KeyN:
            return "N";
        case KeyCode.KeyO:
            return "O";
        case KeyCode.KeyP:
            return "P";
        case KeyCode.KeyQ:
            return "Q";
        case KeyCode.KeyR:
            return "R";
        case KeyCode.KeyS:
            return "S";
        case KeyCode.KeyT:
            return "T";
        case KeyCode.KeyU:
            return "U";
        case KeyCode.KeyV:
            return "V";
        case KeyCode.KeyW:
            return "W";
        case KeyCode.KeyX:
            return "X";
        case KeyCode.KeyY:
            return "Y";
        case KeyCode.KeyZ:
            return "Z";

        case KeyCode.Semicolon:
            return ";";
        case KeyCode.Slash:
            return "/";
        case KeyCode.Backspace:
            return "Backspace";
        case KeyCode.CapsLock:
            return "CapsLock";
        case KeyCode.ContextMenu:
            return "ContextMenu";
        case KeyCode.Enter:
            return "Enter";
        case KeyCode.Space:
            return "Space";
        case KeyCode.Tab:
            return "Tab";
        case KeyCode.Convert:
            return "Convert";

        case KeyCode.Delete:
            return "Delete";
        case KeyCode.End:
            return "End";
        case KeyCode.Help:
            return "Help";
        case KeyCode.Home:
            return "Home";
        case KeyCode.Insert:
            return "Insert";
        case KeyCode.PageDown:
            return "PageDown";
        case KeyCode.PageUp:
            return "PageUp";

        case KeyCode.ArrowDown:
            return "Down";
        case KeyCode.ArrowUp:
            return "Up";
        case KeyCode.ArrowLeft:
            return "Left";
        case KeyCode.ArrowRight:
            return "Right";

        case KeyCode.NumLock:
            return "NumLock";
        case KeyCode.NumpadAdd:
            return "NumAdd";
        case KeyCode.NumpadBackspace:
            return "NumBackspace";
        case KeyCode.NumpadClear:
            return "NumClear";
        case KeyCode.NumpadClearEntry:
            return "NumClearEntry";
        case KeyCode.NumpadComma:
            return "NumComma";
        case KeyCode.NumpadDecimal:
            return "NumDecimal";
        case KeyCode.NumpadDivide:
            return "NumDivide";
        case KeyCode.NumpadSubtract:
            return "NumSubtract";
        case KeyCode.NumpadEnter:
            return "NumEnter";
        case KeyCode.NumpadEqual:
            return "NumEqual";
        case KeyCode.NumpadMultiply:
            return "NumMultiply";
        case KeyCode.NumpadStar:
            return "NumStar";

        case KeyCode.Escape:
            return "Esc";
        case KeyCode.Fn:
            return "Fn";
        case KeyCode.FnLock:
            return "FnLock";
        case KeyCode.PrintScreen:
            return "PrintScreen";
        case KeyCode.ScrollLock:
            return "ScrollLock";

        case KeyCode.Pause:
            return "Pause";

        case KeyCode.AudioVolumeMute:
            return "VolumeMute";
        case KeyCode.AudioVolumeDown:
            return "VolumeDown";
        case KeyCode.AudioVolumeUp:
            return "VolumeUp";
        case KeyCode.MediaTrackNext:
            return "MediaNextTrack";
        case KeyCode.MediaTrackPrevious:
            return "MediaPreviousTrack";
        case KeyCode.MediaPlayPause:
            return "MediaPlayPause";
        case KeyCode.LaunchMail:
            return "LaunchMail";
        case KeyCode.LaunchApp1:
            return "LaunchApp1";
        case KeyCode.LaunchApp2:
            return "LaunchApp2";

        case KeyCode.Suspend:
            return "Suspend";
        case KeyCode.F1:
            return "F1";
        case KeyCode.F2:
            return "F2";
        case KeyCode.F3:
            return "F3";
        case KeyCode.F4:
            return "F4";
        case KeyCode.F5:
            return "F5";
        case KeyCode.F6:
            return "F6";
        case KeyCode.F7:
            return "F7";
        case KeyCode.F8:
            return "F8";
        case KeyCode.F9:
            return "F9";
        case KeyCode.F10:
            return "F10";
        case KeyCode.F11:
            return "F11";
        case KeyCode.F12:
            return "F12";
        case KeyCode.F13:
            return "F13";
        case KeyCode.F14:
            return "F14";
        case KeyCode.F15:
            return "F15";
        case KeyCode.F16:
            return "F16";
        case KeyCode.F17:
            return "F17";
        case KeyCode.F18:
            return "F18";
        case KeyCode.F19:
            return "F19";
        case KeyCode.F20:
            return "F20";
        case KeyCode.F21:
            return "F21";
        case KeyCode.F22:
            return "F22";
        case KeyCode.F23:
            return "F23";
        case KeyCode.F24:
            return "F24";
        case KeyCode.F25:
            return "F25";
        case KeyCode.F26:
            return "F26";
        case KeyCode.F27:
            return "F27";
        case KeyCode.F28:
            return "F28";
        case KeyCode.F29:
            return "F29";
        case KeyCode.F30:
            return "F30";
        case KeyCode.F31:
            return "F31";
        case KeyCode.F32:
            return "F32";
        case KeyCode.F33:
            return "F33";
        case KeyCode.F34:
            return "F34";
        case KeyCode.F35:
            return "F35";
        default:
            return "";
    }
}
